%!Tex Program = xelatex
%\documentclass[a4paper]{article}
\documentclass[a4paper]{ctexart}
\usepackage{xltxtra}
\usepackage{listings}
%\setmainfont[Mapping=tex-text]{AR PL UMing CN:style=Light}
%\setmainfont[Mapping=tex-text]{AR PL UKai CN:style=Book}
%\setmainfont[Mapping=tex-text]{WenQuanYi Zen Hei:style=Regular}
%\setmainfont[Mapping=tex-text]{WenQuanYi Zen Hei Sharp:style=Regular}
%\setmainfont[Mapping=tex-text]{AR PL KaitiM GB:style=Regular} 
%\setmainfont[Mapping=tex-text]{AR PL SungtiL GB:style=Regular} 
%\setmainfont[Mapping=tex-text]{WenQuanYi Zen Hei Mono:style=Regular} 


\title{HW03 继续完成 第三讲：Linux 环境和 Shell 编程（原书P34-65}
\author{3220101611 韩耀霆}
\date{\today}

\begin{document}
\maketitle
\pagestyle{empty}


\section{重定向、管道}

Shell 中一切都是文件，包括标准输入输出。比如 \verb|ls -l| 的输出结果默认是输出到 \verb|stdout|，
也就是标准输出设备，但你可以用重定向操作符将其重定向为一个文件，比如：

\begin{lstlisting}[language=sh]
  ls -l > output.txt
\end{lstlisting}

这个就是把 \verb|ls -l| 的输出结果保存在 \verb|output.txt| 中。 

操作符 \verb|>| 是重写一个新文件，而 \verb|>>| 是追加在原文件末尾。

我们知道除了标准输出文件 \verb|stdout|，还有一个标准错误文件 \verb|stderr|，
这个往往和 \verb|stdout| 指向同一个输出设备。但可以通过重定向分离。
一般默认的输出是标准输出文件，而 2 则值标准错误文件。比如：
 
\begin{lstlisting}[language=sh]
  kill -HUP 1234
\end{lstlisting}

删除进程 1234, 显示

\begin{lstlisting}[language=sh]
  bash: kill: (1234) - No such process
\end{lstlisting}

因为一般不会正好有这个进程号。这里全部都是标准错误文件输出的，所以如果运行

\begin{lstlisting}[language=sh]
  kill -HUP 1234 > output.txt
\end{lstlisting}

则得到一个空文本文件。要

\begin{lstlisting}[language=sh]
  kill -HUP 1234 2> output.txt
\end{lstlisting}

才能截获错误信息到文本文件。如果我们想同时截获标准输出和错误输出并放在一个文件里，可以

\begin{lstlisting}[language=sh]
  kill -HUP 1234 >killout.txt 2>&1
\end{lstlisting}

注意，\verb|2>&1| 之间不能有空格。如果输出中有很多垃圾信息你不想看，
可以将其重定向到一个垃圾桶：

\begin{lstlisting}[language=sh]
  kill -l 1234 2>/dev/null
\end{lstlisting}

既然标准输出可以重定向，标准输入自然也可以

\begin{lstlisting}[language=sh]
  ls ~ -lR > output.txt
\end{lstlisting}

先搞一个大一点的输出，把它丢给 \verb|more| 做输入，功能是把输入一屏幕一屏幕输出。

\begin{lstlisting}[language=sh]
  more < output.txt
\end{lstlisting}

注意这里操作符反向了。

然后这里有一件很土的事情，就是这个
\verb|output.txt| 就是一个中转站，何必一定要存下来呢？就不能直接转移过去？
也就是把一个命令的输出当作另一个命令的输入。这个当然可以，就叫管道，
操作符是 \verb|||。

\begin{lstlisting}[language=sh]
  ls ~ -lR | more
\end{lstlisting}

大家可能注意到我曾经在输出中只显示有关键字的部分，用的也是管道：

\begin{lstlisting}[language=sh]
  ls ~ -lR | grep usr
\end{lstlisting}

管道和重定向可以根据需要多重连接。


\section{循环过程}

Shell 提供了表示循环和分支判定的结构，如：

\begin{lstlisting}[language=sh]
  for file in *
    do
    if grep -l figure $file
    then
      ls $file -l
    fi
  done
\end{lstlisting}

是一个循环结构，\verb|file| 是一个用户定义的变量，
\verb|*| 表示当前目录下所有文件，\verb|in| 表示遍历。
所以这段命令的意思就是遍历当前目录下所有文件，对每个文件重复做
\verb|...something...| 这件事。比如：

\begin{lstlisting}[language=sh]
  for fAd in *
    do
    echo $fAd
  done
\end{lstlisting}

就是遍历当前目录，将全部文件名都打印一遍。命令 \verb|echo| 是打印输出的意思。


\section{分支过程}

然后看内层是一个分支结构：

\begin{lstlisting}[language=sh]
  if [ ...condition... ]
  then
    ...do something...
  fi
\end{lstlisting}

以上是一个标准的 \verb|if ... fi| 结构。但我们用的时候没有
\verb|...condition...|，类似 C 语言，只要 \verb|...condition...| 部分不为空，
我们就认为条件是真。所以这里的意思是

\begin{lstlisting}[language=sh]
  if grep -l figure $file
  then
    ls $file -l
  fi
\end{lstlisting}

只要

\begin{lstlisting}[language=sh]
  grep -l figure $file
\end{lstlisting}

过滤的结果不为空，即之前遍历到的 \verb|$file| 这些文件里存在包含 \verb|figure|
单词的，就把它的详细信息列出来。你自己可以根据需要做自由的调整，比如：

\begin{lstlisting}[language=sh]
  for file in *
    do
    if grep -l figure $file
    then
      cp $file ~/Documents
    fi
  done
\end{lstlisting}

这是什么意思？已经具有收集功能了。


\section{通配符（wildcard expansion）}

注意到这里 \verb|*| 是一个典型的通配符，意思是全部文件；类似的通配符还有：

\begin{itemize}

\item \verb|?|，任一单个字符，比如：\verb|lec0?|，那么
  \verb|lec01|，\verb|lec02| 和 \verb|lec0k| 都匹配；
  \verb|[]|，括号中任一字母。比如：\verb|lec0[abc]|，那么
  \verb|lec0a|，\verb|lec0b| 和 \verb|lec0c| 都匹配；
\item \verb|[^]| 或 \verb|[!]|, 不含括号内的任一字符，比如：\verb|lec0[!12]|，
  那么 \verb|lec01| 和 \verb|lec02| 都不匹配；

\item \verb|{}|，包含大括号内任一字串，比如：\verb|lec03{.log,.pdf}| 则匹配
    \verb|lec03.pdf| 或 \verb|lec03.log|。

\end{itemize}

以上通配符可自由组合，比如：\verb|*0?.{t??,a*}|。

然后 \verb|$| 操作符主要有两个意思，要么是表示将一个变量替换成变量值，如之前的 \verb|$file|；
也可以表示对命令的替换。比如：

\begin{lstlisting}[language=sh]
  grep -l crazyfish *
\end{lstlisting}

表示列出目录下所有含有 \verb|crazyfish| 字符串的文件名，那么

\begin{lstlisting}[language=sh]
  ls -l $(grep -l crazyfish *)
\end{lstlisting}

就表示进一步列出这些文件的详细信息。


\section{脚本代码 (script)}

现在我们可以用连续的命令加上流程控制加上通配符实现比较复杂的功能。
这些命令可以形成一个脚本，并用 bash 去运行。具体做法是依次写下命令，
然后在第一行写上 \verb|#!/bin/bash| 表示这个脚本用哪个 shell 执行。
下面是一个完整的脚本的例子：

\begin{lstlisting}[language=sh]
  #!/bin/sh
  # first
  # This file looks through all the files in the current
  # directory for the string POSIX, and then prints the names of
  # those files to the standard output.
  for file in *
    do
    if grep -q crazyfish $file 
    then
      echo $file 
    fi
  done
  exit 0
\end{lstlisting}

将它存成一个文本文件，比如叫 \verb|test.sh|，然后将其设置成可执行，
然后就可以像运行一个命令一样运行它。实际上，它构成一个组合命令，或称批处理。
这里 \verb|grep -q| 表示安静地运行，或者说，不要实际输出，因为我们这里只要求
\verb|grep| 返回是否找到这样一个状态就行。


\section{变量}

既然可以写脚本了，变量自然很重要。这里变量直接使用就可以：

\begin{lstlisting}[language=sh]
  salutation=Hello
  echo $salutation
\end{lstlisting}

一赋值一输出。默认就是字符串，引不引号无所谓：

\begin{lstlisting}[language=sh]
  salutation="Yes Dear"
  echo $salutation
\end{lstlisting}

就算是给数字，还是字符串：

\begin{lstlisting}[language=sh]
  salutation=7+5
  echo $salutation
\end{lstlisting}

命令 \verb|read| 可以由用户给变量赋值：

\begin{lstlisting}[language=sh]
  read salutation
  echo $salutation
\end{lstlisting}

从上面的过程我们可以看到，在 shell 中，双引号和不加引号都是字符串，
而单引号和 \verb|\| 才是真正的引号：

\begin{lstlisting}[language=sh]
  #!/bin/sh
  myvar="Hi there"
  echo $myvar
  echo "$myvar"
  echo '$myvar'
  echo \$myvar
  echo Enter some text
  read myvar
  echo '$myvar' now equals $myvar
  exit 0
\end{lstlisting}
(参见：example/scripts/quoting.sh)


\section{环境变量}

除了我们自定义的变量，shell 还内置了很多环境变量，供我们和系统交互。

\begin{itemize}

\item \verb|$HOME|，用户目录；

\item \verb|$PATH|，执行程序的路径，放在这些路径下的可执行文件能够直接被运行；

\item \verb|$PS1|，命令行提示符，普通用户是 \verb|$|，超级用户是 \verb|#|；

\item \verb|$PS2|，第二提示符，比如等待输入状态，通常是 \verb|>|；

\item \verb|$IFS|，输入参数的间隔符，一般是一个空格，也可以是 TAB 或换行；

\end{itemize}

以上都可以用 \verb|echo| 输出查看。但是

\begin{lstlisting}[language=sh]
  echo $PS1
\end{lstlisting}

会得到

\begin{lstlisting}[language=sh]
  ${debian_chroot:+($debian_chroot)}\u@\h:\w\$
\end{lstlisting}

这里转义字符 \verb|\u| 表示用户名，\verb|\h| 表示主机名，\verb|\w| 表示当前路径。
以下环境变量专门给 scripts 使用，

\begin{itemize}

\item \verb|$0|，脚本名；

\item \verb|$#|，传递给脚本的参数个数；

\item \verb|$$|，脚本的进程编号；

\item \verb|$1|，\verb|$2|，...，传递给脚本的第 1 个，第 2 个参数，...；

\item \verb|$*|，传递给脚本的全部参数，作为一个字符串；

\item \verb|$@|，传递给脚本的全部参数，有几个参数就是几个字符串；

\end{itemize}

测试脚本(try\_var.sh)

\begin{lstlisting}[language=sh]
  #!/bin/bash

  echo “The program $0 is now running”
  echo “The first parameter was $1”
  echo “The second parameter was $2”
  echo “The third parameter was $3”
  echo “The all parameters were $*“

  echo “The parameter list was:“
  for para in $@
    do
    echo $para
  done

  exit 0
\end{lstlisting}

体会一下 \verb|@*| 和 \verb|$@| 的区别。


\section{判断条件（condition）}

实际上，正经的 \verb|if| 后面应该跟一个条件判断，条件的写法是：

\begin{lstlisting}[language=sh]
  if ...condition...
\end{lstlisting}

这里 \verb|...condition...| 的有两种表达，\verb|test| 或者 \verb|[  ]|，
后者方括号两端必须各有一个空格。

\begin{table}[]
\caption{字符串逻辑运算关系表}
\centering
\begin{tabular}{|c|c|}
\hline
字符串比较 & 结果 \\
\hline
string1 = string2 & True 如果字符串相等 \\
\hline
string1 != string2 & True 如果字符串不想等 \\
\hline
-n string & True 如果字符串非空 \\
\hline
-z string & True 如果字符串空 \\
\hline
\end{tabular}
\end{table}

\begin{table}[]
\caption{算术逻辑运算关系表}
\centering
\begin{tabular}{|c|c|}
\hline
算术表达式 & 结果 \\
\hline
expression1 -eq expression2 & True 如果表达式值相等\\
\hline
expression1 -ne expression2 & True 如果表达式值不想等\\
\hline
expression1 -gt expression2 & True 如果 expression1 大于 expression2\\
\hline
expression1 -ge expression2 & True 如果 expression1 大于等于 expression2\\
\hline
expression1 -lt expression2 & True 如果 expression1 小于 expression2\\
\hline
expression1 -le expression2 & True 如果 expression1 小于等于 expression2\\
\hline
! expression & True 如果 expression false, 或反之\\
\hline
\end{tabular}
\end{table}

\begin{table}[]
\caption{文件逻辑运算关系表}
\centering
\begin{tabular}{|c|c|}
\hline
文件判断 & 结果 \\
\hline
-d file & True 如果 file 是目录\\
\hline
-e file & True 如果 file 存在\\
\hline
-f file & True 如果 file 是正经的文件\\
\hline
-g file & True 如果 file 设置了 group id\\
\hline
-r file & True 如果 file 可读\\
\hline
-s file & True 如果 file 大小不是零\\
\hline
-u file & True 如果 file 设置了 user id\\
\hline
-w file & True 如果 file 可写\\
\hline
-x file & True 如果 file 可执行\\
\hline
\end{tabular}
\end{table}


\section{控制结构}

在shell脚本中，控制结构（语句）主要有以下几部分：

\begin{itemize}

\item \verb|if|:根据条件的结果执行不同的代码块，类似于其他编程语言。
  if语句的基本语法如下:

\begin{lstlisting}[language=sh]
  if condition
  then
    statements
  else
    statements
  fi
  \end{lstlisting}
 
\item  \verb|elif|:在解决问题过程中可能会遇到需要判断多个条件的情况，
  此时需要在\verb|if|的基础上增加\verb|elif|，其基本语法如下:

\begin{lstlisting}[language=sh]
  if condition
  then
    statements
  elif condition
    statements
  ...
  else
    statements
  fi
  \end{lstlisting}

\textbf{注}:当变量为空字符串时，在使用\verb|if|语句进行比较时会导致错误。为了避免这种情况，在变量周围使用引号来确保正确的比较。使用引号后，即使变量为空字符串，也能进行有效的比较。
 
\item \verb|for|:通过\verb|for|循环可以遍历一系列的值，这些值可以是在程序中列出的，也可以是通过文件名进行Shell扩展得到的。\verb|for|循环的语法简单明了:

\begin{lstlisting}[language=sh]
  for variable in values
  do 
    statements
  done
\end{lstlisting}

\item \verb|while|:当需要重复执行一系列命令，但无法事先确定需要执行的次数时，通常使用\verb|while|循环。\verb|while|循环的语法如下:

\begin{lstlisting}[language=sh]
  while condition
  do
    statements
  done
\end{lstlisting}

循环体内的命令将会一直执行，直到条件变为假为止。
  
\item \verb|until|:\verb|until|循环与\verb|while|循环类似，但条件的测试相反。也就是说，在\verb|until|循环中，循环会一直执行直到条件变为真而不是条件为真时执行,其基本语法如下:

\begin{lstlisting}[language=sh]
  until condition
  do
    statements
  done
\end{lstlisting}

\item \verb|case|:\verb|case|语句比之前介绍的控制结构略复杂，但非常强大。它允许按照模式对变量的内容进行匹配，并根据匹配结果执行相应的语句块。\verb|case|语句通常用于处理用户输入,其基本语法如下:
  
\begin{lstlisting}[language=sh]
  case variable in
    pattern1) statements ;;
    pattern2) statements ;;
    ...
  esac
\end{lstlisting}
  
\item \verb|Lists|:当语句运行与多个条件相关时，可以考虑使用\verb|List|将他们连接起来以避免程序过分臃肿，典型的有\verb|AND Lists|和\verb|OR Lists|,其分别是:
  
1、\verb|AND List|:允许执行一系列命令，只有在前面的所有命令都成功执行后才会执行下一个命令，其语法为:
  
\begin{lstlisting}[language=sh]
  statement1 && statement2 && statement3 && ...
\end{lstlisting}
  
2、\verb|OR Lists|:允许执行一系列命令，直到有一个命令成功执行为止，之后不再执行其他命令，其语法为:

\begin{lstlisting}[language=sh]
  statement1 || statement2 || statement3 || ...
\end{lstlisting}

\textbf{注}::如果要在只允许一个语句的位置使用多个语句，例如在 AND 或 OR 列表中，可以通过将它们放在大括号 {} 中来制作语句块以使得语句合法。

\end{itemize}


\section{函数}

类似于其他编程语言，我们同样可以在shell中定义并调用函数来组织代码。定义 shell 中的函数，其基本语法结构如下:

\begin{lstlisting}[language=sh]
  function_name () {
    statements
  }
\end{lstlisting}

额外地，在调用一个函数前要确保在前文已有关于这个函数的定义，以免出现相关bug。


\section{命令}

在shell脚本中我们可以执行两种类型的命令:外部命令和内置命令，内置命令在系统启动时就调入内存，是常驻内存的，所以执行效率高，而外部命令是系统的软件功能，用户需要时才从硬盘中读入内存，其主要有以下几种类型。

\begin{itemize}

\item \verb|break|:用于在\verb|for|、\verb|while|或\verb|until|循环之前提前退出循环，但一般情况下这会使得脚本较难阅读，语法类似于其他编程语言（例如C++等），给出例子如下：

\begin{lstlisting}[language=sh]
  for file in fred*
  do
    if [ -d “$file” ]; then
      break;
    fi
  done
\end{lstlisting}

\item \verb|:| :"\verb|:|"是一个空命令，即true的别名，常用于简化条件逻辑中，由于它是内置的，运行速度比true快，尽管它的输出的可读性也低得多。它常被用作 \verb|while| 循环的条件或是构造变量条件。

\item \verb|continue|:\verb|continue|用于在循环中跳过当前迭代并进入下一次迭代，其主要用法和优缺点类似于\verb|break|，给出例子如下：
    
\begin{lstlisting}[language=sh]
  for file in fred*
  do
    if [ -d “$file” ]; then
      echo “skipping directory $file”
      continue
    fi
    echo file is $file
  done
\end{lstlisting}

\item \verb|.| :"\verb|.|"用于在当前Shell中执行命令，给出例子如下：

\begin{lstlisting}[language=sh]
  . ./shell_script
\end{lstlisting}
    
\item \verb|echo|:\verb|echo|是 Linux 中最基本和最常用的命令之一，传递给 echo 的参数被打印到标准输出中，其基本语法如下：

\begin{lstlisting}[language=sh]
  echo [-neE] [ARGUMENTS]
\end{lstlisting} 
   
\item \verb|eval|:\verb|eval|可以读取一连串的参数，然后按照参数特性来执行（扫描两次）。参数数目不限，彼此之间用分号隔开

\item \verb|exec|:\verb|exec|用于调用并执行指定的命令（可以调用其他的命令）。如果在当前终端中使用命令，则当指定的命令执行完毕后会立即退出终端。其基本语法如下：

\begin{lstlisting}[language=sh]
  exec [-cl] [-a name] [command [arguments]]
\end{lstlisting} 

\item \verb|exit n|:\verb|exit n|用于退出目前的shell,执行exit可使shell以指定的状态值退出。若不设置状态值参数，则shell以预设值退出。状态值0代表执行成功，其他值代表执行失败。exit也可用在script，离开正在执行的script，回到shell。其基本语法如下：

\begin{lstlisting}[language=sh]
  exit [状态符]
\end{lstlisting} 

\item \verb|export|:\verb|export|用于设置或显示环境变量。在 shell 中执行程序时，shell 会提供一组环境变量。export 可新增，修改或删除环境变量，供后续执行的程序使用。其基本语法如下：

\begin{lstlisting}[language=sh]
  export [-fnp][变量名称]=[变量设置值]
\end{lstlisting}    

\textbf{注}:\verb|export|的效力仅限于该次登陆操作。

\item \verb|expr|:\verb|expr|是一个手工命令行计数器，用于在UNIX/LINUX下求表达式变量的值，一般用于整数值，也可用于字符串。其基本语法如下：

\begin{lstlisting}[language=sh]
  expr statements
\end{lstlisting}    
 
\begin{table}[]
\caption{expr命令表达式计算结果}
\centering
\begin{tabular}{|c|c|}
\hline
算术表达式 & 描述 \\
\hline
expr1 | expr2 & 当expr1非零时输出expr1，否则输出expr2\\
\hline
expr1 = expr2 & expr1 与 expr2相等\\
\hline
expr1 > expr2 & expr1 大于 expr2\\
\hline
expr1 >= expr2 & expr1 大于等于 expr2\\
\hline
expr1 < expr2 & expr1 小于 expr2\\
\hline
expr1 =< expr2 & expr1 小于等于 expr2\\
\hline
expr1 != expr2 & expr1 不等于 expr2\\
\hline
expr1 + expr2 & 对 expr1 和 expr2 做加法运算\\
\hline
expr1 - expr2 & 对 expr1 和 expr2 做减法运算\\
\hline
expr1 * expr2 & 对 expr1 和 expr2 做乘法运算\\
\hline
expr1 / expr2 & 对 expr1 和 expr2 做除法取整运算\\
\hline
expr1 \% expr2 & 对 expr1 和 expr2 做除法取余运算\\
\hline
\end{tabular}
\end{table}

\item \verb|printf|:\verb|printf|是shell中除了\verb|echo|的另一个输出命令\verb|printf|。\verb|printf|命令是模仿 C 程序库（library）里的 \verb|printf()|程序。由于\verb|printf()|由 POSIX 标准所定义，因此使用\verb|printf()|的脚本比使用 \verb|echo|移植性好。\verb|printf|使用引用文本或空格分隔的参数，外面可以在 \verb|printf|中使用格式化字符串，还可以制定字符串的宽度、左右对齐方式等。默认的\verb|printf|不会像\verb|echo|自动添加换行符，我们可以手动添加 \verb|\n|。其基本语法如下：

\begin{lstlisting}[language=sh]
  printf format-string [arguments...]
\end{lstlisting}  

\begin{table}[]
\caption{printf支持的转义符号}
\centering
\begin{tabular}{|c|c|}
\hline
转义表达式 & 简述 \\
\hline
\verb|\"| & 双引号\\
\hline
\verb|\\| & 反斜线符\\
\hline
\verb|\a| & 警报（按铃声或嘟嘟声）\\
\hline
\verb|\b| & 回退字符\\
\hline
\verb|\c| & 抑制进一步输出\\
\hline
\verb|\f| & 表单源字符\\
\hline
\verb|\n| & 换行符\\
\hline
\verb|\r| & 回车键\\
\hline
\verb|\t| & 制表符\\
\hline
\verb|\v| & 垂直制表符\\
\hline
\verb|\ooo| & 8进制单个字符\\
\hline
\verb|\xHH| & 16进制单个字符\\
\hline
\end{tabular}
\end{table}

\begin{table}[]
\caption{printf支持输出转换符}
\centering
\begin{tabular}{|c|c|}
\hline
转换符 & 简述 \\
\hline
D & 输出十进制数\\
\hline
C & 输出字符\\
\hline
S & 输出字符串\\
\hline
\% & 输出百分数\\
\hline
\end{tabular}
\end{table}

\item \verb|return|:\verb|return|是使得shell函数退出并返回数值，如果没有指定n的值，则默认为函数最后一条命令执行的返回状态。 返回值为你指定的参数n的值，如果你指定的参数大于255或小于0，那么会通过加或减256的方式使得返回值总是处于0到255之间。在函数外执行\verb|return|语句会返回失败。

\item \verb|set|:\verb|set|用于设置shell。\verb|set|指令能设置所使用shell的执行方式，可依照不同的需求来做设置。

\item \verb|shift|:\verb|shift|用于向左移动参数，能够将命令接收到的参数逐个向左移动一位，即原本的\$3变量会覆盖\$2变量，原本的\$2变量会覆盖\$1变量，这样我们只需要每执行一次shift命令后调用\$1变量。其基本语法如下：

\begin{lstlisting}[language=sh]
  shift [parameter]
\end{lstlisting}

\item \verb|trap|:\verb|trap|允许我们来指定shell脚本要监视并拦截的Linux信号。\verb|trap|命令的格式为：

\begin{lstlisting}[language=sh]
  trap commands signals
\end{lstlisting}

\begin{table}[]
\caption{X/Open 标准涵盖的可捕获的信号}
\centering
\begin{tabular}{|c|c|}
\hline
信号 & 简述 \\
\hline
HUP (1)  & 挂起进程\\
\hline
INT (2) & 终止进程\\
\hline
QUIT (3) & 停止进程\\
\hline
ABRT (6) & 自动报错\\
\hline
ALRM (14) & 设置定时器\\
\hline
TERM (15) & 尽可能终止进程\\
\hline
\end{tabular}
\end{table}

\item \verb|unset|:\verb|unset|用于删除变量或函数，其基本语法为:

\begin{lstlisting}[language=sh]
  unset [-fv][parameter or function name]
\end{lstlisting}

\item \verb|find|:\verb|find|用于在指定目录下查找文件和目录,它可以使用不同的选项来过滤和限制查找的结果。

\begin{table}[]
\caption{find Command中查找选项}
\centering
\begin{tabular}{|c|c|}
\hline
选项 & 简述 \\
\hline
-depth  & 先搜索目录的内容，然后再查看目录本身\\
\hline
-follow & 如果遇到符号链接文件，就跟踪链接所指的文件\\
\hline
-maxdepths N & 搜索时最多搜索目标目录以下的 N 级子目录\\
\hline
-mount (or -xdev) & 不要搜索其他文件系统上的目录\\
\hline
\end{tabular}
\end{table}

\begin{table}[]
\caption{find Command中查找内容}
\centering
\begin{tabular}{|c|c|}
\hline
选项 & 简述 \\
\hline
-atime N  & 按文件访问时间来查找文件，-N指N天以内，+N指N天以前\\
\hline
-mtime N & 按文件更改时间来查找文件，-N指N天以内，+N指N天以前\\
\hline
-name pattern & 搜索时使用 pattern 对文件名进行匹配\\
\hline
-newer otherfile  & 查找比另一文件更新的文件\\
\hline
-type b/d/c/p/l/f  & 查找是块设备、目录、字符设备、管道、符号链接、普通文件\\
\hline
-user username  & 按文件属主来查找\\
\hline
\end{tabular}
\end{table}

\begin{table}[]
\caption{find Command中内容连接符}
\centering
\begin{tabular}{|c|c|c|}
\hline
操作符（简化） & 操作符（复杂） & 简述 \\
\hline
!  & -not & 对内容取反\\
\hline
-a & -and & 同时为真\\
\hline
-o & -or & 其中一者为真\\
\hline
\end{tabular}
\end{table}

\item \verb|grep|:\verb|grep|用于查找内容包含指定的范本样式的文件，如果发现某文件的内容符合所指定的范本样式，预设 grep 指令会把含有范本样式的那一列显示出来。若不指定任何文件名称，或是所给予的文件名为 -，则 grep 指令会从标准输入设备读取数据。

\begin{table}[]
\caption{grep Command中查找选项}
\centering
\begin{tabular}{|c|c|}
\hline
选项 & 简述 \\
\hline
-c & 只打印匹配的行数\\
\hline
-E & 将样式为延伸的正则表达式来使用\\
\hline
-h & 在显示符合样式的那一行之前，不标示该行所属的文件名称\\
\hline
-i & 忽略大小写进行匹配。\\
\hline
-l & 只打印匹配的文件名\\
\hline
-v & 反向查找，只打印不匹配的行\\
\hline
\end{tabular}
\end{table}

\end{itemize}

\bibliographystyle{plain}
\bibliography{crazyfish.bib}

\end{document}
